package com.starview.star.compiler.transform.monasticate;

import com.starview.star.compiler.canonical.Application;
import com.starview.star.compiler.canonical.AssertAction;
import com.starview.star.compiler.canonical.Assignment;
import com.starview.star.compiler.canonical.CaseAction;
import com.starview.star.compiler.canonical.CaseExpression;
import com.starview.star.compiler.canonical.CastExpression;
import com.starview.star.compiler.canonical.CastPtn;
import com.starview.star.compiler.canonical.ConditionCondition;
import com.starview.star.compiler.canonical.ConditionalAction;
import com.starview.star.compiler.canonical.ConditionalExp;
import com.starview.star.compiler.canonical.Conjunction;
import com.starview.star.compiler.canonical.ConstructorPtn;
import com.starview.star.compiler.canonical.ConstructorTerm;
import com.starview.star.compiler.canonical.ContentCondition;
import com.starview.star.compiler.canonical.Disjunction;
import com.starview.star.compiler.canonical.EnvironmentEntry.ContractEntry;
import com.starview.star.compiler.canonical.EnvironmentEntry.ImplementationEntry;
import com.starview.star.compiler.canonical.EnvironmentEntry.ImportEntry;
import com.starview.star.compiler.canonical.EnvironmentEntry.TypeAliasEntry;
import com.starview.star.compiler.canonical.ExceptionHandler;
import com.starview.star.compiler.canonical.FalseCondition;
import com.starview.star.compiler.canonical.FieldAccess;
import com.starview.star.compiler.canonical.ForLoopAction;
import com.starview.star.compiler.canonical.FunctionLiteral;
import com.starview.star.compiler.canonical.ICondition;
import com.starview.star.compiler.canonical.IContentAction;
import com.starview.star.compiler.canonical.IContentExpression;
import com.starview.star.compiler.canonical.IContentPattern;
import com.starview.star.compiler.canonical.IStatement;
import com.starview.star.compiler.canonical.Ignore;
import com.starview.star.compiler.canonical.Implies;
import com.starview.star.compiler.canonical.IsTrue;
import com.starview.star.compiler.canonical.JavaEntry;
import com.starview.star.compiler.canonical.LetAction;
import com.starview.star.compiler.canonical.LetTerm;
import com.starview.star.compiler.canonical.ListSearch;
import com.starview.star.compiler.canonical.Matches;
import com.starview.star.compiler.canonical.MatchingPattern;
import com.starview.star.compiler.canonical.MemoExp;
import com.starview.star.compiler.canonical.Negation;
import com.starview.star.compiler.canonical.NullAction;
import com.starview.star.compiler.canonical.NullExp;
import com.starview.star.compiler.canonical.OpenStatement;
import com.starview.star.compiler.canonical.Otherwise;
import com.starview.star.compiler.canonical.Overloaded;
import com.starview.star.compiler.canonical.OverloadedFieldAccess;
import com.starview.star.compiler.canonical.PatternAbstraction;
import com.starview.star.compiler.canonical.PatternApplication;
import com.starview.star.compiler.canonical.ProcedureCallAction;
import com.starview.star.compiler.canonical.RaiseAction;
import com.starview.star.compiler.canonical.RaiseExpression;
import com.starview.star.compiler.canonical.RecordTerm;
import com.starview.star.compiler.canonical.RecordPtn;
import com.starview.star.compiler.canonical.RecordSubstitute;
import com.starview.star.compiler.canonical.RegExpPattern;
import com.starview.star.compiler.canonical.Resolved;
import com.starview.star.compiler.canonical.Scalar;
import com.starview.star.compiler.canonical.ScalarPtn;
import com.starview.star.compiler.canonical.Search;
import com.starview.star.compiler.canonical.Sequence;
import com.starview.star.compiler.canonical.Shriek;
import com.starview.star.compiler.canonical.SyncAction;
import com.starview.star.compiler.canonical.TransformAction;
import com.starview.star.compiler.canonical.TransformCondition;
import com.starview.star.compiler.canonical.TransformExpression;
import com.starview.star.compiler.canonical.TransformPattern;
import com.starview.star.compiler.canonical.TransformStatement;
import com.starview.star.compiler.canonical.TrueCondition;
import com.starview.star.compiler.canonical.TypeDefinition;
import com.starview.star.compiler.canonical.TypeWitness;
import com.starview.star.compiler.canonical.ValisAction;
import com.starview.star.compiler.canonical.ValofExp;
import com.starview.star.compiler.canonical.VarDeclaration;
import com.starview.star.compiler.canonical.VarEntry;
import com.starview.star.compiler.canonical.Variable;
import com.starview.star.compiler.canonical.VoidExp;
import com.starview.star.compiler.canonical.WherePattern;
import com.starview.star.compiler.canonical.WhileAction;
import com.starview.star.compiler.canonical.Yield;
import com.starview.star.compiler.util.Lambda;
import com.starview.star.compiler.util.Pair;

public class Monasticate
    implements
    TransformAction<Trafo<IContentAction>, Trafo<IContentExpression>, IContentPattern, Trafo<ICondition>, IStatement, Void>,
    TransformExpression<Trafo<IContentAction>, Trafo<IContentExpression>, IContentPattern, Trafo<ICondition>, IStatement, Void>,
    TransformPattern<Trafo<IContentAction>, Trafo<IContentExpression>, IContentPattern, Trafo<ICondition>, IStatement, Void>,
    TransformCondition<Trafo<IContentAction>, Trafo<IContentExpression>, IContentPattern, Trafo<ICondition>, IStatement, Void>,
    TransformStatement<Trafo<IContentAction>, Trafo<IContentExpression>, IContentPattern, Trafo<ICondition>, IStatement, Void>
{

  @Override
  public IStatement transformContractDefn(ContractEntry con, Void context)
  {
    return con;
  }

  @Override
  public IStatement transformContractImplementation(ImplementationEntry entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformImportEntry(ImportEntry entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformJavaEntry(JavaEntry entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformTypeAliasEntry(TypeAliasEntry entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformTypeEntry(TypeDefinition entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformVarEntry(VarEntry entry, Void context)
  {
    return entry;
  }

  @Override
  public IStatement transformOpenStatement(OpenStatement open, Void context)
  {
    return open;
  }

  @Override
  public IStatement transformWitness(TypeWitness stmt, Void context)
  {
    return stmt;
  }

  @Override
  public Trafo<ICondition> transformConditionCondition(ConditionCondition conditionCondition, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformConjunction(Conjunction conjunction, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformDisjunction(Disjunction disjunction, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformFalseCondition(FalseCondition falseCondition, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformImplies(Implies implies, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformIsTrue(IsTrue i, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformListSearch(ListSearch ptn, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformMatches(Matches matches, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformNegation(Negation negation, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformOtherwise(Otherwise otherwise, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformSearch(Search predication, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<ICondition> transformTrueCondition(TrueCondition trueCondition, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformRecordPtn(RecordPtn aggregatePtn, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformCastPtn(CastPtn ptn, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformMatchingPtn(MatchingPattern matches, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformPatternApplication(PatternApplication apply, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformRegexpPtn(RegExpPattern ptn, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformScalarPtn(ScalarPtn scalar, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformConstructorPtn(ConstructorPtn tuplePtn, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformVariablePtn(Variable variable, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public IContentPattern transformWherePattern(WherePattern wherePattern, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformApplication(final Application appl, final Void context)
  {
    IContentExpression fun = appl.getFunction();
    final IContentExpression arg = appl.getArgs();
    return combine(fun.transform(this, context), new Lambda<IContentExpression, Trafo<IContentExpression>>() {

      @Override
      public Trafo<IContentExpression> apply(final IContentExpression dFun)
      {
        return combine(arg.transform(Monasticate.this, context),
            new Lambda<IContentExpression, Trafo<IContentExpression>>() {

              @Override
              public Trafo<IContentExpression> apply(IContentExpression dArg)
              {
                return encap((IContentExpression) new Application(appl.getLoc(), appl.getType(), dFun, dArg));
              }
            });
      }

    });
  }

  @Override
  public Trafo<IContentExpression> transformRecord(RecordTerm record, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformRecordSubstitute(RecordSubstitute update, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformCaseExpression(CaseExpression exp, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformCastExpression(CastExpression exp, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformConditionalExp(ConditionalExp act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformContentCondition(ContentCondition cond, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformMemo(MemoExp memo, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformNullExp(NullExp nil, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformFunctionLiteral(FunctionLiteral f, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformLetTerm(LetTerm let, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformOverloaded(Overloaded over, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformOverloadedFieldAccess(OverloadedFieldAccess over, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformPatternAbstraction(PatternAbstraction pattern, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformFieldAccess(FieldAccess dot, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformRaiseExpression(RaiseExpression exp, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformReference(Shriek reference, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformResolved(Resolved res, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformScalar(Scalar scalar, Void context)
  {
    return encap((IContentExpression) scalar);
  }

  @Override
  public Trafo<IContentExpression> transformConstructor(ConstructorTerm tuple, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformValofExp(ValofExp val, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentExpression> transformVariable(Variable variable, Void context)
  {
    return encap((IContentExpression) variable);
  }

  @Override
  public Trafo<IContentExpression> transformVoidExp(VoidExp exp, Void context)
  {
    return encap((IContentExpression) exp);
  }

  @Override
  public Trafo<IContentAction> transformAssertAction(AssertAction act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformAssignment(Assignment act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformCaseAction(CaseAction exp, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformConditionalAction(ConditionalAction act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformExceptionHandler(ExceptionHandler handler, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformForLoop(ForLoopAction loop, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformIgnored(Ignore ignore, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformLetAction(LetAction let, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformWhileLoop(WhileAction act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformNullAction(NullAction act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformProcedureCallAction(ProcedureCallAction call, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformRaiseAction(RaiseAction raise, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformSequence(Sequence sequence, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformSyncAction(SyncAction sync, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformValisAction(ValisAction act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformVarDeclaration(VarDeclaration var, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Trafo<IContentAction> transformYield(Yield act, Void context)
  {
    // TODO Auto-generated method stub
    return null;
  }

  private static <T> Trafo<T> encap(final T s)
  {
    return new Trafo<T>() {

      @Override
      public <S> Pair<T, S> apply(S a)
      {
        return Pair.pair(s, a);
      }
    };
  }

  private static <U, V> Trafo<V> combine(final Trafo<U> enc, final Lambda<U, Trafo<V>> comb)
  {
    return new Trafo<V>() {

      @Override
      public <S> Pair<V, S> apply(S a)
      {
        Pair<U, S> XX = enc.apply(a);
        return comb.apply(XX.left).apply(XX.right);
      }
    };
  }
}
